#ifndef LECTEURPHRASEAVECARBRE_H_
#define LECTEURPHRASEAVECARBRE_H_

#include "Symbole.h"
#include "LecteurSymbole.h"
#include "TableSymboles.h"
#include "Arbre.h"

#include <string>
using namespace std;

/*! \file LecteurPhraseAvecArbre.h
    \brief La spécification de la classe LecteurPhraseAvecArbre
    \author Cedric Vierne et Sergio Vasquez
    \date 18.04.2011
 */

/*! \class LecteurPhraseAvecArbre
    \brief  Elle consiste en la création d'une table de symbole et d'un arbre abstrait grâce à l'analyse du lecteur de phrases
 */


class LecteurPhraseAvecArbre
{
public:
    
    /*! \fn LecteurPhraseAvecArbre
        \brief  Construit un lecteur de phrase pour interpreter le programme dans le fichier nomFich
        \param string nomFich
    */
	LecteurPhraseAvecArbre(string nomFich);	 
        
        
    /*! \fn analyse()
        \brief  Si le contenu du fichier est conforme à la grammaire, cette méthode se termine normalement et affiche un message "Syntaxe correcte".
     * la table des symboles (ts) et l'arbre abstrait (arbre) auront été construits. Sinon, le programme sera interrompu (exit).
        \param aucun
    */
	void analyse(); 

    /*! \fn TableSymboles getTs ()
        \brief accesseur
        \param aucun
     *  \return TableSymboles
    */
	inline TableSymboles getTs ()    { return ts;    }

    /*! \fn Noeud* getArbre ()
        \brief accesseur
        \param aucun
     *  \return Noeud* arbre
    */
	inline Noeud*        getArbre () { return arbre; } 
	

private:

    /*! \fn LecteurSymbole ls
        \brief le lecteur de symboles utilisé pour analyser le fichier
    */
    LecteurSymbole ls;

    /*! \fn TableSymboles  ts
        \brief la table des symboles valués
    */
    TableSymboles  ts;

    /*! \fn Noeud* arbre
        \brief l'arbre abstrait
    */
    Noeud*         arbre;

    // implémentation de la grammaire

    /*! \fn Noeud*  programme()
        \brief  <programme> ::= debut <seqInst> fin FIN_FICHIER
    */
    Noeud*  programme();

    /*! \fn Noeud*  seqInst
        \brief  <seqInst> ::= <inst> ; { <inst> ; }
    */
    Noeud*  seqInst();

    /*! \fn Noeud*  inst();
        \brief <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter>
    */
    Noeud*  inst();

    /*! \fn  Noeud*  affectation()
        \brief <affectation> ::= <variable> = <expression>
    */
    Noeud*  affectation();

    /*! \fn Noeud*  expression()
        \brief  <expression> ::= <facteur> { <opAdd> <facteur> }
    */
    Noeud*  expression();

    /*! \fn Noeud* facteur()
        \brief <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  ( <expression> )
    */
    Noeud* facteur();

    /*! \fn Noeud* terme()
        \brief <terme>::=<facteur>{<oppMult><facteur>}
    */
    Noeud* terme();

    /*! \fn Symbole opAdd()
        \brief <opAdd>:: = + | -
    */
    Symbole opAdd();

    /*! \fn Symbole oppMult()
        \brief l<opMult>::=* | /
    */
    Symbole oppMult();

    /*! \fn  Noeud* expBoolOu()
        \brief <expBoolOu>::=<expBoolEt> {ou} <expBoolEt>}
    */
    Noeud* expBoolOu();

    /*! \fn Noeud* expBoolEt()
        \brief <expBoolEt>::=<expression> {et <expression>}
    */
    Noeud* expBoolEt();

    /*! \fn Noeud* relation()
        \brief <relation>::=<expresion>{<opRel><expression>}
    */
    Noeud* relation();

    /*! \fn Symbole opRel()
        \brief <opRel>::= == | != | <= | < | > | >=
    */
    Symbole opRel();

    /*! \fn Symbole opUnaire()
        \brief <opUnaire>::= - | non
    */
    Symbole opUnaire();

    /*! \fn Noeud* instSi()
        \brief <instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> }[ sinon <seqInst> ] finsi
    */
    Noeud* instSi();

    /*! \fn Noeud* instTq()
        \brief <instTq> ::= tantque ( <expBool> ) <seqInst> fintantque
    */
    Noeud* instTq();

    /*! \fn Noeud* instRepeter()
        \brief <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
    */
    Noeud* instRepeter(); 

    /*! \fn Noeud* instLire()
        \brief
    */
    Noeud* instLire();

    /*! \fn Noeud* instEcrire()
        \brief
    */
    Noeud* instEcrire();

    /*! \fn Noeud* instPour()
        \brief
    */
    Noeud* instPour();

    /*! \fn Noeud* instSwitchCase()
        \brief
    */
    Noeud* instSwitchCase();

    // outils pour se simplifier l'analyse syntaxique
    void testerSymCour (string ch);  // si symbole courant != ch, erreur : on arrete le programme, sinon rien
    void sauterSymCour (string ch);  // si symbole courant == ch, on passe au symbole suivant, sinon erreur : on arrete
    void erreur (string mess);      // affiche les message d'erreur mess et arrete le programme
};

#endif /* LECTEURPHRASEAVECARBRE_H_ */
